<?php

class ORM {
	const ORDER_DESC = 'DESC';
	const ORDER_ASC = 'ASC';

	private $workTable = '';
	private $relations = array();
	private $limit = null;
	private $order = array();
	private $getCount = false;
	private $result = null;
	private $data = array();
	private $join = array();
	private $query = '';
	private $resultArray = array();
	private $workOffset = null;
	private $condition = null;

	/**
     * @return ORM
     */
	public static function connect($table) {
		return new ORM($table);
	}

	/**
     * @return ORM
     */
	private function __construct($table) {
		$this->workTable = $table;
	}


	/**
     * @return ORM
     */
	public function __call($method, $arguments) {
		if (sizeof($arguments) == 1) {//set data
			$this->__set($method, $arguments[0]);
		} elseif (sizeof($arguments) == 0) {//get data
			$this->__get($method);
		} else {
			// wtf ??
		}
		return $this;
	}

	/**
     * @return ORM
     */
	public function __get($name) {
		if (isset($this->data[$name])) {
			return $this->data[$name];
		}
		if (isset($this->resultArray[$this->workOffset][$name])) {
			return $this->resultArray[$this->workOffset][$name];
		}
		return $this;
	}

	/**
     * @return ORM
     */
	public function __set($name, $value) {
		$this->data[$name] = $this->escape($value);
		return $this;
	}

	public function update($condition = '') {
		$this->condition = $condition;
		$this->prepareQuery('update');
		Mysql::getInstance()->query($this->query);
		return $this;
	}

	/**
     * @return ORM
     */
	public function get($offset = null) {
		if (sizeof($this->resultArray) && is_int($offset)) {
			$this->workOffset = $offset;
		} else {
			$this->prepareQuery('select');
			$this->result = Mysql::getInstance()->query($this->query);
			$this->toArray();
		}
		return $this;
	}

	/**
     * @return ORM
     */
	public function limit($limit, $offset = 0) {
		$lim = ' ';
		if ($offset) {
			$lim .= $offset . ', ';
		}
		$lim .= strval($limit);
		$this->limit = $lim;
		return $this;
	}

	/**
     * @return ORM
     */
	public function order($byFieldname, $ordertype = self::ORDER_DESC) {
		if (!in_array($ordertype, array(self::ORDER_ASC, self::ORDER_DESC))) {
			$ordertype = self::ORDER_DESC;
		}
		$this->order[$byFieldname] = $ordertype;
		return $this;
	}

	/**
     * @return ORM
     */
	public function join($with, $fieldFirst, $fieldSecond) {
		$this->join[] = array(
		'with' => $with,
		'field' => $fieldFirst,
		'on_field' => $fieldSecond,
		);
		return $this;
	}

	/**
     * @return ORM
     */
	public function getCount() {
		if (!$this->getCount && !sizeof($this->resultArray)) {
			$this->getCount = true;
		} else {
			$result = Mysql::getInstance()->getarray("SELECT FOUND_ROWS()");
			return intval($result['FOUND_ROWS()']);
		}

		return $this;
	}

	private function escape($string) {
		return addslashes($string);
	}

	public function toArray() {
		if (sizeof($this->resultArray)) {
			return $this->resultArray;
		} else {
			$res = array();
			while ($r = Mysql::fetch_assoc($this->result)) {
				$r = array_map('stripslashes', $r);
				$res[] = $r;
			}
			if (sizeof($res) === 1 && is_array($res)) {
				$res = $res[0];
			}
			$this->resultArray = $res;
			return $res;
		}
	}

	private function prepareQuery($type) {
		switch ($type) {
			case 'insert':

				break;
			case 'update':
				if (!sizeof($this->data)) {
					return;
				}
				$query[] = 'UPDATE';
				$query[] = PREFIX . '_' . $this->workTable;
				$query[] = 'SET';

				foreach ($this->data as $field => $val) {
					$q[] = $field . '=\'' . $val . '\'';
				}
				$query[] = implode(',', $q);

				$query[] = 'WHERE';

				if (!is_int($this->workOffset) && sizeof($this->resultArray)) {
					$identificator = '';
					$values = array();
					foreach ($this->resultArray as $offset => $result) {
						if (!$identificator) {
							$i = array_keys($result);
							$identificator = $i[0];
						}
						$values[] = $result[$identificator];
					}
					$query[] = 'IN (' . join(',', $values) . ')';
				} elseif (is_int($this->workOffset) && sizeof($this->resultArray)) {
					$i = array_keys($this->resultArray[$this->workOffset]);
					$identificator = $i[0];
					$val = $this->resultArray[$this->workOffset][$identificator];
					if (!is_numeric($val)) {
						$val = '\'' . $val . '\'';
					}
					$query[] = $identificator . '=' . $val;
				} elseif (!sizeof($this->resultArray) && $this->condition) {
					$query[] = $this->condition;
				} else return;

				$this->query = join(' ', $query);
				break;
			case 'delete':

				break;
			case 'select':
				$query[] = 'SELECT';

				if ($this->getCount) {
					$query[] = 'SQL_CALC_FOUND_ROWS';
				}

				$query[] = '*';

				$query[] = 'FROM `' . PREFIX . '_' . $this->workTable . '`';

				if (sizeof($this->join)) {
					foreach ($this->join as $join) {
						$query[] = 'LEFT JOIN `' . PREFIX . '_' . $join['with'] . '` ON';
						$query[] = PREFIX . '_' . $this->workTable . '.' . $join['field'] . '=' . PREFIX . '_' . $join['with'] . '.' . $join['on_field'];
					}
				}

				if (sizeof($this->data)) {
					$where = array();
					$query[] = 'WHERE';
					foreach ($this->data as $field => $val) {
						$where[] = $field . '=\'' . $val . '\'';
					}
					$query[] = implode(' AND ', $where);
				}

				if (sizeof($this->order)) {
					$order = array();
					$query[] = 'ORDER BY';
					foreach ($this->order as $field => $type) {
						$order[] = $field . ' ' . $type;
					}
					$query[] = join(',', $order);
				}

				if ($this->limit) {
					$query[] = 'LIMIT' . $this->limit;
				}

				$this->query = join(' ', $query);
				break;
		}
	}
	
	private function getFirstKey($array){
		$keys = array_keys($array);
		return $keys[0];
	}
}

